
package com.phevos.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.util.Properties;

import org.apache.oro.text.regex.MatchResult;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.slf4j.LoggerFactory;


public final class FileUtil
{

    private static String FILE_PATH_SEPERATOR = null;

    /**
     * ��ȡ�ļ�·����ķָ����unixϵͳ�Ͻ�����"/",��windows�Ϸ���"\"
     * 
     * @author zhaoch
     * @return �ļ�·���ķָ��
     */
    public static String getFilePathSeperator()
    {
        if (FILE_PATH_SEPERATOR == null)
        {
            FILE_PATH_SEPERATOR = System.getProperty("file.separator");
        }
        if (FILE_PATH_SEPERATOR == null)
        {
            FILE_PATH_SEPERATOR = "/";
        }
        return FILE_PATH_SEPERATOR;
    }

    /**
     * ���ļ��ж�ȡ����
     * 
     * @param filename ��ȡ������ļ���
     * @return ���ļ��ж�ȡ�Ķ���
     * @author zhaoch
     */
    public static Object readObjFromFile(String filename)
    {
        Object obj = null;
        ObjectInputStream ois = null;
        FileInputStream fis = null;

        try
        {
            fis = new FileInputStream(filename);
            ois = new ObjectInputStream(fis);
            obj = ois.readObject();
            return obj;
        }
        catch (FileNotFoundException fne)
        {
            return null;
        }
        catch (Exception ex)
        {
            LoggerFactory.getLogger(FileUtil.class.getName()).error("when read object from " + filename,
                    ex);
            return null;
        }
        finally
        {
            try
            {
                if (ois != null)
                {
                    ois.close();
                }
            }
            catch (IOException ie)
            {
            }
        }
    }

    /**
     * ǿ�ƽ�һ�����д���ļ�������ļ����������ȴ����ļ�
     * 
     * @param filename ����д���ļ���
     * @param obj Ҫд��Ķ���
     * @param append �Ƿ�׷�ӡ����򸲸�;�ǣ���׷��
     * @throws IOException
     * @author zhaoch
     */
    public static void forceWriteObjToFile(String filename, Object obj, boolean append)
            throws IOException
    {
        File file = new File(filename);
        ObjectOutputStream oos = null;
        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream(file);
            oos = new java.io.ObjectOutputStream(fos);
            if (file.exists())
            {
                oos.writeObject(obj);
            }
            else
            {
                file.createNewFile();
                oos.writeObject(obj);
            }
        }
        finally
        {
            if (fos != null)
            {
                try
                {
                    fos.close();
                }
                catch (Throwable t)
                {
                }
            }
            if (oos != null)
            {
                try
                {
                    oos.reset();
                    oos.close();
                }
                catch (Throwable t)
                {
                }
            }
        }
    }

    /**
     * ��һ���ļ��жs���ʱ��long���
     * 
     * @param filename ����ʱ����ļ���
     * @return �ļ��б����ʱ��
     */
    public static long getLongFormFile(String filename)
    {
        FilePosition pos = (FilePosition)getPositionFormFile(filename);
        if (pos == null)
        {
            return -1;
        }
        else
        {
            return pos.getLongData();
        }
    }

    /**
     * ��long���д��ָ�����ļ���
     * 
     * @param filename ����д���ļ���
     * @param l Ҫд���long�������
     * @return д��ɹ�����true�����򷵻�false
     */
    public static boolean setLongToFile(String filename, long l)
    {
        FilePosition pos = new FilePosition();
        pos.setLongData(l);
        if (setPositionToFile(filename, pos))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * ���ļ���ȡһ��Serializable����
     * 
     * @param filename �u��ļ���
     * @return Serializable����
     */
    public static Serializable getPositionFormFile(String filename)
    {
        File posFile = null;
        ObjectInputStream in = null;
        try
        {
            posFile = new File(filename);
            if (posFile.exists())
            {
                in = new ObjectInputStream(new FileInputStream(posFile));
                return (Serializable)in.readObject();
            }
        }
        catch (Throwable t)
        {
            return null;
        }
        finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException ex)
                {
                }
            }
        }
        return null;
    }

    /**
     * ��һ��Serializable���󱣴浽�ļ���
     * 
     * @param filename ���������ļ���
     * @param pos Ҫ�����Serializable����
     * @return ����ɹ�����true�����򷵻�false
     */
    public static boolean setPositionToFile(String filename, Serializable pos)
    {
        File posFile = new File(filename);
        if (!posFile.exists())
        {
            try
            {
                posFile.createNewFile();
            }
            catch (IOException ex2)
            {
                return false;
            }
        }
        ObjectOutputStream out = null;
        try
        {
            out = new ObjectOutputStream(new FileOutputStream(posFile));
            out.writeObject(pos);
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
            return false;
        }
        finally
        {
            if (out != null)
            {
                try
                {
                    out.reset();
                    out.close();
                }
                catch (IOException ex1)
                {
                }
            }
        }
        return true;
    }

    /**
     * ��һ���ļ��вɼ���� �÷������ϴβɼ��Ľ���λ�ÿ�ʼֱ���ļ���β,�ɼ�����ƥ��ʽ���ַ� ����¼�ϴβɼ�λ�õ���ʱ�ļ�û�ҵ�,����βɼ�����null,��¼�ļ����ܳ���Ϊ���βɼ���λ��
     * ����ļ��ĳ���С���ϴβɼ���λ��,����βɼ�����null,��¼�ļ����ܳ���Ϊ���βɼ���λ�� һ�βɼ����ܷ��ض��ֵ,֮����sepvalue�ָ�
     * ����һ��ֵ����������ʽ�е�group,ÿ��group�м���sepgroup�ָ�
     * 
     * @param filename �ɼ���ݵ��ļ���
     * @param tmpfile ��¼�ļ�λ�õ���ʱ�ļ���
     * @param match ����ƥ����ʽ
     * @param sepgroup ���ص�һ��ɼ�����зָ��
     * @param sepvalue ���صĶ���ɼ����֮��ķָ��
     * @return
     */
    public static String collectFromFile(String filename, String tmpfile, String match,
            String sepgroup, String sepvalue)
    {
        RandomAccessFile file = null;
        long length;
        long filelength = -1;
        String value = null;
        length = getLongFormFile(tmpfile);
        if (length > 0)
        {
            value = collectFromFileBeginLine(filename, length, match, sepgroup, sepvalue);
        }
        try
        {
            file = new RandomAccessFile(filename, "r");
            filelength = file.length();
        }
        catch (Exception ex)
        {
            return null;
        }
        finally
        {
            if (filelength > 0)
            {
                setLongToFile(tmpfile, filelength);
            }
            if (file != null)
            {
                try
                {
                    file.close();
                }
                catch (IOException ex1)
                {
                }
            }
        }
        return value;
    }

    /**
     * ��һ���ļ��е�ָ��λ�ÿ�ʼ�ɼ�,���زɼ��Ľ�� һ�βɼ����ܷ��ض��ֵ,֮����sepvalue�ָ� ����һ��ֵ����������ʽ�е�group,ÿ��group�м���sepgroup�ָ�
     * 
     * @param filename �ļ���
     * @param line �ɼ���λ��
     * @param match ����ƥ����ʽ
     * @param sepgroup ���ص�һ��ɼ�����зָ��
     * @param sepvalue ���صĶ���ɼ����֮��ķָ��
     * @return
     */
    public static String collectFromFileBeginLine(String filename, long line, String match,
            String sepgroup, String sepvalue)
    {
        RandomAccessFile file = null;
        long filelength;
        try
        {
            file = new RandomAccessFile(filename, "r");
            filelength = file.length();
        }
        catch (Exception ex)
        {
            closeRandomAccessFile(file);
            return null;
        }
        int lines = getLinesFromExp(match);
        String[] readLines = new String[lines];
        String matchLine = "";
        if (line >= filelength)
        {
            closeRandomAccessFile(file);
            return null;
        }
        try
        {
            file.seek(line);
        }
        catch (IOException ex1)
        {
            closeRandomAccessFile(file);
            return null;
        }
        try
        {
            String strTmp = null;
            int index = 0;
            while (index < readLines.length)
            {
                strTmp = file.readLine();
                if (strTmp == null)
                {
                    return null;
                }
                if (strTmp.trim().length() == 0)
                {
                    continue;
                }
                readLines[index++] = strTmp;
            }
        }
        catch (Exception e)
        {
            closeRandomAccessFile(file);
            return null;
        }
        String result = null;
        MatchResult matchResult = null;
        PatternMatcher matcher = new Perl5Matcher();
        PatternCompiler compiler = new Perl5Compiler();
        try
        {
            while (true)
            {
                matchLine = readLines[0];
                for (int i = 1; i < readLines.length; i++)
                {
                    matchLine += '\n' + readLines[i];
                }
                Pattern patten = compiler.compile(match);
                if (matcher.contains(matchLine, patten))
                {
                    matcher.matches(matchLine, patten);
                    matchResult = matcher.getMatch();
                    String values = null;
                    for (int i = 0; i < matchResult.groups(); i++)
                    {
                        if (values == null)
                        {
                            values = matchResult.group(i);
                        }
                        else
                        {
                            values += sepgroup + matchResult.group(i);
                        }
                    }
                    if (result == null)
                    {
                        result = values;
                    }
                    else
                    {
                        result += sepvalue + values;
                    }
                }
                for (int i = 0; i < readLines.length - 1; i++)
                {
                    readLines[i] = readLines[i + 1];
                }
                String strTmp = null;
                while (true)
                {
                    strTmp = file.readLine();
                    if (strTmp == null || strTmp.trim().length() > 0)
                    {
                        break;
                    }
                }
                if (strTmp == null)
                {
                    break;
                }
                readLines[readLines.length - 1] = strTmp;
            }
        }
        catch (Throwable t)
        {
        }
        finally
        {
            closeRandomAccessFile(file);
        }
        return result;
    }

    /**
     * ����һ�������ļ���Properties �ڳ��ʱ���ؿ�
     * 
     * @param filename Properties�ļ���
     * @return Properties����
     */
    public static Properties getPropertiesFromFile(String filename)
    {
        Properties prop = null;
        File configFile = null;
        FileInputStream configStream = null;
        try
        {
            prop = new Properties();
            configFile = new File(filename);
            configStream = new FileInputStream(configFile);
            prop.load(configStream);
            configStream.close();
            return prop;
        }
        catch (Exception e)
        {
            return null;
        }
        finally
        {
            if (configStream != null)
            {
                try
                {
                    configStream.close();
                }
                catch (IOException ex)
                {
                }
            }
        }
    }

    /**
     * �ر�һ��RandomAccessFile�ļ���
     * 
     * @param file RandomAccessFile Ҫ�رյ��ļҷ�
     */
    public static void closeRandomAccessFile(RandomAccessFile file)
    {
        if (file != null)
        {
            try
            {
                file.close();
            }
            catch (IOException ex)
            {
            }
        }
    }

    /**
     * ���������ʽ�����Ҫƥ�������
     * 
     * @param exp ԭʼ�ַ�
     * @return int ����
     */
    private static int getLinesFromExp(String exp)
    {
        return StringUtil.containSubstring(exp, "\\n") + 1;
    }

    /**
     * ��һ���ļ���׷���ַ�����
     * 
     * @param log String Ҫ׷�ӵ��ַ�
     * @param fileName String Ҫд����ļ���
     */
    public static void appendLog(String log, String fileName)
    {
        RandomAccessFile file = null;
        try
        {
            file = new RandomAccessFile(fileName, "rw");
            file.seek(file.length());
            file.writeBytes(log + "\n");
        }
        catch (Exception ex)
        {

        }
        finally
        {
            closeRandomAccessFile(file);
        }
    }

    /**
     * ��֤һ���ַ�Ϊ��Ч�ļ����������ļ����в�������ַ���������ַ�ȥ��
     * 
     * @param fileName String ԭʼ�ַ�
     * @return String ��Ч���ļ���
     */
    public static String validateFileName(String fileName)
    {
        char[] ilChar = new char[]{'\\', '/', ':', '*', '?', ':', '<', '>', '|'};
        StringBuffer buff = new StringBuffer();
        for (int i = 0; i < fileName.length(); i++)
        {
            char ch = fileName.charAt(i);
            if (!isInArr(ch, ilChar))
            {
                buff.append(ch);
            }
        }
        return buff.toString();
    }

    private static boolean isInArr(char ch, char[] arr)
    {
        for (int i = 0; i < arr.length; i++)
        {
            if (ch == arr[i])
            {
                return true;
            }
        }
        return false;
    }

    /**
     * �ļ��е����ݽṹ
     */
    public static class FilePosition implements java.io.Serializable
    {
        /**
         * 
         */
        private static final long serialVersionUID = 2429782519099469461L;
        private long pointer;

        public long getLongData()
        {
            return pointer;
        }

        public void setLongData(long l)
        {
            pointer = l;
        }
    }

}
